package com.plat.api.api.action;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayOrderReverseRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderReverseResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.plat.api.anonation.NoToken;
import com.plat.api.anonation.Token;
import com.plat.api.api.action.common.CommonMethod;
import com.plat.api.api.action.common.UserInfo;
import com.plat.api.common.OrderType;
import com.plat.api.common.RespCode;
import com.plat.api.config.WxPayCommentConfig;
import com.plat.api.dao.api.*;
import com.plat.api.entity.RepGoodsInfo;
import com.plat.api.entity.api.*;
import com.plat.api.exception.PlatException;
import com.plat.api.mapper.PlatGoodMapper;
import com.plat.api.redis.RedisCache;
import com.plat.api.util.SnowflakeIdWorker;
import com.plat.api.util.StringUtil;
import com.plat.api.util.YmalPropertiesUtil;
import org.apache.commons.lang3.StringUtils;
import org.beetl.sql.core.engine.PageQuery;
import org.beetl.sql.core.query.LambdaQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * author ss
 * createTime 2020/5/8
 * package ${com.example.demo.controller.action}
 ***/
@Component
@Token
public class OrderAction {
    @Autowired
    private PlatOrderDao orderDao;
    @Autowired
    private PlatOrderDetailDao detailDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private TokenDao tokenDao;
    @Autowired
    private PlatVideoDao platVideoDao;
    @Autowired
    private PlatAuctionDao platAuctionDao;
    @Autowired
    private PlatAddressDao platAddressDao;
    @Autowired
    private PlatExpressInfoDao platExpressInfoDao;
    @Autowired
    private PlatRefundApplyDao refundApplyDao;
    @Autowired
    private WxPayService wxService;

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private PlatWechatLiveRoomDao roomDao;
    @Autowired
    private PlatGoodMapper platGoodMapper;

    /**
     * 查询订单的通用接口
     */
    @NoToken
    public Object orderList(JSONObject jsonObject) {
        JSONObject body = jsonObject.getJSONObject("body");
        Integer page = body.getInteger("page");
        Integer pageSize = body.getInteger("pageSize");
        Integer type = body.getInteger("type");
        UserEntity userEntity = UserInfo.getUserEntity(jsonObject, userDao, tokenDao);
        //全部
        Map allResult = new HashMap();
        if (type == 0) {
            PageQuery<PlatOrderEntity> all = orderDao.createLambdaQuery().andEq("user_id", userEntity.getId()).orderBy("id desc").andNotEq("order_type",OrderType.VIDE0)
                    .andNotEq("order_type",OrderType.LIVE).page(page, pageSize);
            allResult.put("status", "all");
            allResult.put("list", getJsonObject(all.getList(), userEntity));
        }
        //待支付
        Map wp = new HashMap();
        if (type == 1) {
            PageQuery<PlatOrderEntity> waitPay = orderDao.createLambdaQuery().andEq("user_id", userEntity.getId()).andEq("pay_status", 0).andNotEq("order_status",OrderType.ORDER_CANCEL).orderBy("id desc").andNotEq("order_type",OrderType.VIDE0)
                    .andNotEq("order_type",OrderType.LIVE).page(page, pageSize);
            wp.put("status", "waitPay");
            wp.put("list", getJsonObject(waitPay.getList(), userEntity));
        }
        //待发货
        Map we = new HashMap();
        if (type == 2) {
            PageQuery<PlatOrderEntity> waitExpress = orderDao.createLambdaQuery().andEq("user_id", userEntity.getId())
                    .andEq("pay_status", 1).andEq("express_status", OrderType.ORDER_EXPRESS_NO_DISTRIBUTE).andEq("refund_status", OrderType.ORDER_NO_REFUND)
                    .orderBy("id desc")
                    .andNotEq("order_type",OrderType.VIDE0)
                    .andNotEq("order_type",OrderType.LIVE)
                    .page(page, pageSize);
            we.put("status", "waitExpress");
            we.put("list", getJsonObject(waitExpress.getList(), userEntity));
        }
        //待收货
        Map wt = new HashMap();
        if (type == 3) {
            PageQuery<PlatOrderEntity> waitTake = orderDao.createLambdaQuery().andEq("user_id", userEntity.getId())
                    .andEq("pay_status", 1).andEq("express_status", OrderType.ORDER_EXPRESS_DISTRIBUTE).andEq("refund_status", OrderType.ORDER_NO_REFUND).andNotEq("order_status",OrderType.ORDER_FINISH).orderBy("id desc").page(page, pageSize);
            wt.put("status", "waitTake");
            wt.put("list", getJsonObject(waitTake.getList(), userEntity));

        }
        //完成
        Map fn = new HashMap();
        if (type == 4) {
            PageQuery<PlatOrderEntity> finish = orderDao.createLambdaQuery().andEq("user_id", userEntity.getId())
                    .andEq("pay_status", 1).andEq("order_status", OrderType.ORDER_FINISH).orderBy("id desc").page(page, pageSize);
            fn.put("status", "finish");
            fn.put("list", getJsonObject(finish.getList(), userEntity));
        }
        //退款---显示在下方
        Map rf = new HashMap();
        if (type == 5) {
            PageQuery<PlatOrderEntity> refund = orderDao.createLambdaQuery().andEq("user_id", userEntity.getId())
                    .andEq("pay_status", 1).andEq("order_status", OrderType.ORDER_FINISH)
                    .orEq("refund_status", OrderType.ORDER_REFUNDING)
                    .orEq("refund_status", OrderType.ORDER_REFUND_WAITING)
                    .orEq("refund_status", OrderType.ORDER_REFUND_FINISH)
                    .orEq("refund_status", OrderType.ORDER_REFUND_REJECT).andNotEq("refund_status", OrderType.ORDER_NO_REFUND).orderBy("id desc").page(page, pageSize);

            rf.put("status", "refund");
            Iterator iterator = refund.getList().iterator();
            while (iterator.hasNext()) {
                PlatOrderEntity orderEntity = (PlatOrderEntity) iterator.next();
                if (orderEntity.getRefundStatus().equals(OrderType.ORDER_NO_REFUND)) {
                    iterator.remove();
                }
            }
            rf.put("list", getJsonObject(refund.getList(), userEntity));
        }
        JSONObject result = new JSONObject(true);
        JSONArray array = new JSONArray();
        result.put("all", allResult.isEmpty() ? array : allResult.get("list"));
        result.put("waitPay", wp.isEmpty() ? array : wp.get("list"));
        result.put("waitExpress", we.isEmpty() ? array : we.get("list"));
        result.put("waitTake", wt.isEmpty() ? array : wt.get("list"));
        result.put("finish", fn.isEmpty() ? array : fn.get("list"));
        result.put("refund", rf.isEmpty() ? array : rf.get("list"));
        return result;
    }

    private List<JSONObject> getJsonObjects(JSONObject jsonObject, Integer orderType, Integer payStatus) {
        JSONObject body = jsonObject.getJSONObject("body");
        List<JSONObject> list = new ArrayList<>();
        Integer page = body.getInteger("page");
        Integer pageSize = body.getInteger("pageSize");
        UserEntity userEntity = UserInfo.getUserEntity(jsonObject, userDao, tokenDao);
        PageQuery<PlatOrderEntity> finish;
        if (orderType.equals(00) && orderType.equals(00)) {
            finish = orderDao.createLambdaQuery().andEq("user_id", userEntity.getId()).page(page, pageSize);
        } else {
            finish = orderDao.createLambdaQuery().andEq("user_id", userEntity.getId())
                    .andEq("pay_status", payStatus).andEq("order_status", orderType).page(page, pageSize);
        }
        JSONObject fn = new JSONObject();
        fn.put("status", "finish");
        fn.put("list", getJsonObject(finish.getList(), userEntity));
        list.add(fn);
        return list;
    }

    private List<RepOrderDetail> getJsonObject(List<PlatOrderEntity> list, UserEntity user) {
        List<RepOrderDetail> reList = new ArrayList<>();
        for (PlatOrderEntity order : list) {
            RepOrderDetail orderDetail = new RepOrderDetail();
            orderDetail.setRefundStatus(order.getRefundStatus());
            orderDetail.setUser(JSONObject.toJSON(user));
            BigDecimal expressFee = new BigDecimal(0);
            PlatOrderDetailEntity detailEntity = detailDao.createLambdaQuery().andEq("order_no", order.getOrderNo()).single();
            if (detailEntity != null) {
                orderDetail.setOrderNo(order.getOrderNo());
                orderDetail.setStatus(order.getOrderStatus());
                orderDetail.setOrderType(order.getOrderType());
                orderDetail.setCreatTime(DateUtil.format(order.getCreateTime(), "yyyy-MM-dd hh:mm:ss"));
                if (order.getPayTime() != null) {
                    orderDetail.setPayTime(DateUtil.format(order.getPayTime(), "yyyy-MM-dd hh:mm:ss"));
                }
                if (order.getPayStatus() == 1) {
                    orderDetail.setPayStatus(1);
                } else {
                    orderDetail.setPayStatus(0);
                }
                orderDetail.setOrderStatus(order.getOrderStatus());
                if (order.getOrderType().equals(OrderType.YSP)) {
                    QueryWrapper<PlatGoodsEntity> queryWrapper = new QueryWrapper();
                    queryWrapper.eq("id", detailEntity.getGoodsId());
                    PlatGoodsEntity goodsEntity = platGoodMapper.selectOne(queryWrapper);
//                    AuctionEntity auctionEntity = platAuctionDao.createLambdaQuery().andEq("id", detailEntity.getGoodsId()).single();
                    RepGoodsInfo repGoodsInfo = new RepGoodsInfo();
                    if (goodsEntity != null) {
                        repGoodsInfo.setName(goodsEntity.getGoodsDesc());
                        repGoodsInfo.setExpressFee(new BigDecimal(goodsEntity.getExpressFee()));
                        repGoodsInfo.setImage(StringUtil.solveString(goodsEntity.getGoodsImage()).split(",")[0]);
                        repGoodsInfo.setMoney(new BigDecimal(String.valueOf(order.getOrderPrice())));
                        List<RepGoodsInfo> li = new ArrayList<>();
                        li.add(repGoodsInfo);
                        orderDetail.setExpressStatus(order.getExpressStatus());
                        expressFee = new BigDecimal(goodsEntity.getExpressFee());
                        orderDetail.setOrderTypeName("艺购");
                        orderDetail.setGoodsList(li);
                    }
                } else if (order.getOrderType().equals(OrderType.VIDE0)) {
                    PlatVideoEntity platVideoEntity = platVideoDao.createLambdaQuery().andEq("id", detailEntity.getGoodsId()).single();
                    if (platVideoEntity != null) {
                        RepGoodsInfo repGoodsInfo = new RepGoodsInfo();
                        repGoodsInfo.setName(platVideoEntity.getVideoName());
                        repGoodsInfo.setExpressFee(new BigDecimal(0));
                        repGoodsInfo.setImage(StringUtil.solveString(platVideoEntity.getPoster()));
                        repGoodsInfo.setMoney(new BigDecimal(String.valueOf(order.getOrderPrice())));
                        List<RepGoodsInfo> li = new ArrayList<>();
                        li.add(repGoodsInfo);
                        orderDetail.setExpressStatus(OrderType.NOT_SUPPORTED_EXPRESS);
                        orderDetail.setOrderTypeName("视频");
                        expressFee = new BigDecimal(0);
                        orderDetail.setGoodsList(li);
                    }
                } else if (order.getOrderType().equals(OrderType.LIVE)) {
                    PlatWechatLiveRoomEntity roomEntity = roomDao.createLambdaQuery().andEq("id", detailEntity.getGoodsId()).single();
                    if (roomEntity != null) {
                        RepGoodsInfo repGoodsInfo = new RepGoodsInfo();
                        repGoodsInfo.setName(roomEntity.getName());
                        repGoodsInfo.setExpressFee(new BigDecimal(0));
                        repGoodsInfo.setImage(roomEntity.getCoverImgUrl());
                        repGoodsInfo.setMoney(new BigDecimal(String.valueOf(order.getOrderPrice())));
                        List<RepGoodsInfo> li = new ArrayList<>();
                        li.add(repGoodsInfo);
                        orderDetail.setOrderTypeName("直播订阅");
                        expressFee = new BigDecimal(0);
                        orderDetail.setExpressStatus(OrderType.NOT_SUPPORTED_EXPRESS);
                        orderDetail.setGoodsList(li);
                    }
                }
                orderDetail.setCount(1);
                orderDetail.setCountMoney(order.getOrderRealPrice());
            }
            if (orderDetail.getOrderNo() != null) {
                reList.add(orderDetail);
            }

        }
        return reList;
    }

    public JSONObject orderDetail(JSONObject jsonObject) {
        JSONObject body = jsonObject.getJSONObject("body");
        Integer id = body.getInteger("id");
        PlatOrderEntity order = orderDao.createLambdaQuery().andEq("id", id).single();
        PlatOrderDetailEntity detailEntity = detailDao.createLambdaQuery().andEq("order_no", order.getOrderNo()).single();
        PlatExpressInfoEntity platExpressInfoEntity = platExpressInfoDao.createLambdaQuery().andEq("order_no", order.getOrderNo()).single();
        RepOrderDetail orderDetail = new RepOrderDetail();
        Map<String, Object> result = new HashMap<>();
        if (order.getOrderType().equals(OrderType.AUCTION)) {
            AuctionEntity auctionEntity = platAuctionDao.createLambdaQuery().andEq("id", detailEntity.getGoodsId()).single();
            result.put("name", auctionEntity.getName());
            result.put("price", order.getOrderPrice());
            result.put("createTime", order.getCreateTime());
            result.put("couuponPirce", 0);
            result.put("payTime", order.getPayTime());
            result.put("refundTime", null);
        } else {
            PlatVideoEntity platVideoEntity = platVideoDao.createLambdaQuery().andEq("id", detailEntity.getGoodsId()).single();
            result.put("name", platVideoEntity.getVideoName());
            result.put("price", order.getOrderPrice());
            result.put("createTime", order.getCreateTime());
            result.put("couuponPirce", 0);
            result.put("payTime", order.getPayTime());
            result.put("refundTime", null);
        }
        JSONObject json = new JSONObject();
        json.put("object", result);
        return json;
    }

    /**
     * 退款申请
     */
    public JSONObject refundApply(JSONObject jsonObject) {
        JSONObject body = jsonObject.getJSONObject("body");
        String orderNo = body.getString("orderNo");
        String refundMsg = body.getString("refundMsg");
        UserEntity userEntity = UserInfo.getUserEntity(jsonObject, userDao, tokenDao);
        PlatOrderEntity platOrderEntity = orderDao.createLambdaQuery().andEq("user_id", userEntity.getId())
                .andEq("pay_status", 1).andEq("express_status", OrderType.ORDER_EXPRESS_NO_DISTRIBUTE).andEq("order_no", orderNo).single();
        if (platOrderEntity != null) {
            PlatRefundApplyEntity apply = new PlatRefundApplyEntity();
            apply.setOrderNo(orderNo);
            apply.setRefundNo("");
            apply.setCreateTime(new Date());
            apply.setRefundAmt(platOrderEntity.getOrderPrice().doubleValue());
            apply.setRefundRealAmt(0.0D);
            apply.setFinishTime(new Date());
            apply.setRefundStatus(OrderType.ORDER_REFUND_WAITING);
            apply.setRefundMsg(refundMsg);
            apply.setUserId(userEntity.getId());
            apply.setUserName(userEntity.getName());
            refundApplyDao.insert(apply);
            platOrderEntity.setRefundStatus(OrderType.ORDER_REFUND_WAITING);
            orderDao.updateById(platOrderEntity);
        } else {
            throw new PlatException("退款申请，请申请售后服务！！！");
        }
        JSONObject json = new JSONObject();
        json.put("msg", "申请中");
        return json;
    }

    /**
     * 确认订单
     */
    public JSONObject confirmOrder(JSONObject jsonObject) {
        JSONObject body = jsonObject.getJSONObject("body");
        String orderNo = body.getString("orderNo");
        PlatOrderEntity order = orderDao.createLambdaQuery().andEq("order_no", orderNo).single();
        if (order.getRefundStatus().equals(OrderType.ORDER_FINISH)) {
            throw new PlatException("订单已经完成");
        }
        order.setOrderStatus(OrderType.ORDER_FINISH);
        orderDao.updateById(order);
        JSONObject result = new JSONObject();
        result.put("object", order);
        return result;
    }

    /**
     * 确认取消
     */
    public JSONObject cancelOrder(JSONObject jsonObject) {
        JSONObject body = jsonObject.getJSONObject("body");
        String orderNo = body.getString("orderNo");
        PlatOrderEntity order = orderDao.createLambdaQuery().andEq("order_no", orderNo).single();
        if (order.getOrderStatus().equals(OrderType.ORDER_CANCEL)) {
            throw new PlatException("订单已经取消");
        }
        order.setOrderStatus(OrderType.ORDER_CANCEL);
        orderDao.updateById(order);
        JSONObject result = new JSONObject();
        result.put("object", order);
        return result;
    }

    /**
     * 查看物流信息
     */
    public JSONObject getExpressInfo(JSONObject jsonObject) {
        JSONObject body = jsonObject.getJSONObject("body");
        String orderNo = body.getString("orderNo");
        PlatOrderEntity order = orderDao.createLambdaQuery().andEq("order_no", orderNo).single();
        //调用物流地址查看物流信息
        JSONObject result = new JSONObject();
        result.put("expressInfo", "expressInfo");
        result.put("object", order);
        return result;
    }

    /**
     * 确认重新发起支付
     */
    public JSONObject repay(JSONObject jsonObject) {
        JSONObject body = jsonObject.getJSONObject("body");
        String orderNo = body.getString("orderNo");
        String key = orderNo + "_repay";
        JSONObject result = new JSONObject();
        UserEntity userEntity = CommonMethod.getUserEntity(tokenDao, userDao, jsonObject);
        try {
            if (!redisCache.hasKey(key)) {
                //十五秒之后才可以再次发起支付
                redisCache.setCacheObject(key, orderNo, 15000, TimeUnit.SECONDS);
                PlatOrderEntity order = orderDao.createLambdaQuery().andEq("order_no", orderNo).single();
                PlatOrderDetailEntity detailEntity = detailDao.createLambdaQuery().andEq("order_no", orderNo).single();
                wxService.closeOrder(order.getOrderNo());
                WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
                request.setOpenid(userEntity.getOpenId());
                request.setBody("再次发起支付");
                String outTradeNo = SnowflakeIdWorker.getId();
                order.setOrderNo(outTradeNo);
                detailEntity.setOrderNo(outTradeNo);
                orderDao.updateById(order);
                detailDao.updateById(detailEntity);
                request.setOutTradeNo(outTradeNo);
                Double p;
                if (order.getOrderType().equals(OrderType.YSP)) {
                    p = order.getOrderRealPrice().doubleValue() * 100+order.getExpressFee().doubleValue()*100;
                } else {
                    p = order.getOrderRealPrice().doubleValue()* 100;
                }
                request.setTotalFee(p.intValue());
                request.setSpbillCreateIp("0.0.0.0");
                request.setTradeType("JSAPI");
                WxPayMpOrderResult wxPayMpOrderResult = null;
                if (order.getOrderType().equals(OrderType.YSP)) {
                    wxService.setConfig(WxPayCommentConfig.getYSPNotifyConfig());
                    request.setNotifyUrl(WxPayCommentConfig.getYSPNotifyConfig().getNotifyUrl());
                }
                if (order.getOrderType().equals(OrderType.LIVE)) {
                    wxService.setConfig(WxPayCommentConfig.getSubNotifyConfig());
                    request.setNotifyUrl(WxPayCommentConfig.getYSPNotifyConfig().getNotifyUrl());
                }
                if (order.getOrderType().equals(OrderType.VIDE0)) {
                    wxService.setConfig(WxPayCommentConfig.getVideoNotifyConfig());
                    request.setNotifyUrl(WxPayCommentConfig.getYSPNotifyConfig().getNotifyUrl());
                }
                wxPayMpOrderResult = wxService.createOrder(request);
                result.put("object", order);
                result.put("payInfo", wxPayMpOrderResult);
                result.put("errMsg", "SUCCESS");
                redisCache.deleteObject(key);
            }
        } catch (Exception e) {
            redisCache.deleteObject(key);
            e.printStackTrace();
            result.put("errMsg", e.getMessage());
        }
        return result;
    }
}
